/**
 * Project: complex.java
 * 
 * File Created at 2010-5-27
 * $Id$
 * 
 * Copyright 2008 Alibaba.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Alibaba Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Alibaba.com.
 */
package complex.java.lang.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

/**
 * @description:由class进入的反射机制
 * @author gaoliang
 * @date 2010-5-27
 * @version 1.0
 */
interface GenericInterface {
};

class GenericSuperClass {
};

interface IClassTestA<A, B> extends GenericInterface {
    String printA(A a);
}

interface IClassTestB<A, B> extends GenericInterface {
    String printB(B b);
}

interface IClassTestC extends GenericInterface {
    String printC();
}

class ClassTestC<A, B> extends GenericSuperClass implements IClassTestA<A, B> {
    @Override
    public String printA(A a) {
        System.out.println("this is A:" + a);
        return null;
    }
}

public class ClassTest<A, B> extends ClassTestC<A, B> implements IClassTestB<A, B>, IClassTestC {
    public A       a;
    public B       b;
    private String c;

    private ClassTest() {

    }

    public ClassTest(A a, B b) {
        this.a = a;
        this.b = b;
        System.out.println("constructor :" + a.toString() + b.toString());
    }

    @Override
    public String printB(B b) {
        System.out.println("this is B:" + b);
        return null;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        try {
            Class<ClassTest> classTest = ClassTest.class;
            /** 类所实现的接口 */
            Class[] intf = classTest.getInterfaces();
            for (Class c : intf) {
                System.out.println(c.toString());
            }
            /** 取得接口Type[] */
            Type[] types = classTest.getGenericInterfaces();
            //IClassTestC不属于以下四种子类
            for (Type type : types) {
                if (type instanceof ParameterizedType) {
                    System.out.println("ParameterizedType:" + type.toString());
                    //ParameterizedType:complex.java.lang.IClassTestB<A, B>

                    //取该type的实际类型 Type[] (泛型的实际类型)
                    Type[] ts = ((ParameterizedType) type).getActualTypeArguments();
                    for (Type t : ts) {
                        if (t instanceof ParameterizedType) {
                            //循环了--------------------
                            System.out.println("ParameterizedType:" + t.toString());
                        }
                        if (t instanceof GenericArrayType) {
                            System.out.println("GenericArrayType:" + t.toString());
                        }
                        //A,B就属于此类型
                        if (t instanceof TypeVariable) {
                            System.out.println("TypeVariable:" + t.toString());
                        }
                    }
                }

                //####################################
                if (type instanceof GenericArrayType) {
                    System.out.println("GenericArrayType:" + type.toString());
                }
                if (type instanceof TypeVariable) {
                    System.out.println("TypeVariable:" + type.toString());
                }
                if (type instanceof WildcardType) {
                    System.out.println("WildcardType:" + type.toString());
                }
            }
            /** 取得父类Type */
            Type type = classTest.getGenericSuperclass();
            System.out.println(type.toString());

            /** ############################################# */
            /** 取得属性 */
            ClassTest ct = new ClassTest();
            //public属性
            Field[] fields = classTest.getFields();
            //所有声明的属性
            fields = classTest.getDeclaredFields();
            for (Field field : fields) {
                //field.get(ct)为ct对象的各field值
                System.out.println("ct's" + field.toGenericString() + ":" + field.get(ct));
            }
            /** 取得构造方法 */
            //取得public的构造方法
            Constructor[] constructors = classTest.getConstructors();
            //取得所有声明的构造方法
            constructors = classTest.getDeclaredConstructors();
            for (Constructor constructor : constructors) {
                //构造方法的名称
                System.out.println(constructor.getName());
                //构造方法的 Java 语言修饰符
                System.out.println(constructor.getModifiers());
                Class<?>[] cs = constructor.getParameterTypes();
                for (Class c : cs) {
                    System.out.println("constructor.getParameterTypes" + c.toString());
                }
                System.out.println(constructor.toGenericString());
            }

            /** 取得方法 */
            //public方法
            Method[] methods = classTest.getMethods();
            //所有声明的方法
            methods = classTest.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println(method.toGenericString());
            }
            //取得某个具体方法
            Method method = classTest.getMethod("getTest", String.class);
            //调用ct对象的该方法
            method.invoke(ct, "++++++++++++++this getTest");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public String printC() {
        // TODO Auto-generated method stub
        return null;
    }

    public String getTest(String a) {
        System.out.println(a);
        return null;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

}
